package com.xt.base.wireless.server;

import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import uk.ltd.getahead.dwr.util.Logger;

import com.xt.base.exception.SystemError;

/**
 *  <br>
 * <br>
 * 	解析请求的xml文件，创建结果集的xml文件。
 * <p>
 * <a href="ActionUtil.java.html"><i>查看源文件</i></a>
 * </p>
 * 
 * @author 杨洪波
 * @create-date:2010-11-29
 */
public class MobileActionUtil {
	Logger log = Logger.getLogger(getClass());
	
	/**
	 * 解析手机端发送过来的请求包（xml格式的字符串），解析为Map。
	 * @param xml
	 * @return
	 */
	public static Map<String,Object> parseRequestXml(String xml){
		xml = xml==null?null:xml.trim();
		if(xml.indexOf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")!=0){
			throw new SystemError(new Object(),new Object[]{xml},"不是标准的xml文件，不能解析为Map！");
		}
		Map<String,Object> map = new HashMap<String,Object>();
		try {
			Reader reader = new StringReader(xml);
			Document doc = new SAXReader().read(reader);
			Element root = doc.getRootElement();
			map = dealElements(root);
		}catch (DocumentException e) {
			e.printStackTrace();
		}
		
		return map;
	}
	
	@SuppressWarnings("unchecked")
	private static Map<String,Object> dealElements(Element ele){
		List<Element> elements = ele.elements();
		List<Element> eles     = null;
		Map<String,Object> map = new HashMap<String,Object>();
		String key = null;
		for(Element e : elements){
			key = e.getName();
			if(e.element("list")!=null || "list".equals(key)){//如果下级是列表类型，则生成一个list。
				List<Object> list = new ArrayList<Object>();
				List<Element> tmpLt = "list".equals(key)?e.elements():e.element("list").elements();
				for(Element v : tmpLt){
					if("value".equals(v.getName())){
						if(v.isTextOnly()){
							list.add(v.getText());
						}else{
							//如果下级还有子元素，忽略掉，不予处理。
							list.add(dealElements(v));
						}
					}else{
						//对<list></list>内部，非<value></value>忽略掉，不予处理。
					}
				}
				//list.add(e); 
				map.put(key, list);
			}else if(e.elements()!=null && !e.elements().isEmpty()){
				map.put(key,dealElements(e));
			}else{
				map.put(key, e.getText());
			}
				if(eles!=null && !eles.isEmpty()){
				dealElements(e);
			}
		}
		
		return map;
	}
	
	/**
	 * 把结果集Map转换为xml格式的字符串。Map中，不能包含有自定义对象。
	 * @param map java.util.Map，必须为<String,Object>类型。其中Object
	 * 不能包含自定义类型，只能是java.util.Map、java.util.Set、java.util.Collection、
	 * String[]、Integer[]、Short[]、Long[]、Float[]、Double[]、Boolean[]，
	 * 或者是以上集中类型的Object[]。
	 * @return xml形式的字符串。
	 */
	public static String parseResultMap2Xml(Map<String,Object> map){
		StringBuilder xml = new StringBuilder();
		xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
		.append("<mobile>");
		xml.append(dealMap(map));
		xml.append("</mobile>");
		return xml.toString();
	}
	/**
	 * 转换Map类型为xml字符串。
	 * @param map
	 * @return
	 */
	private static String dealMap(Map<String,Object> map){
		Iterator<Map.Entry<String, Object>> iter = map.entrySet().iterator();
		Map.Entry<String, Object> entry = null;
		StringBuilder xml = new StringBuilder();
		while(iter.hasNext()){
			entry = iter.next();
			xml.append("<").append(entry.getKey()).append(">");
			xml.append(dealObject(entry.getValue()));
			xml.append("</").append(entry.getKey()).append(">");
		}
		
		return xml.toString();
	}
	
	/**
	 * 转换Object类型为xml字符串。
	 * @param o
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static String dealObject(Object o){
		StringBuilder xml = new StringBuilder();
		if(o==null){
			xml.append("");
		}else if(o instanceof String || o instanceof Integer || o instanceof Long 
			|| o instanceof Float || o instanceof Double || o instanceof Boolean){
			xml.append(String.valueOf(o));
			
		}else if(o instanceof Map<?,?>){
			xml.append(dealMap((Map<String,Object>)o));
			
		}else if(o instanceof Collection<?>){
			xml.append(dealCollection((Collection<Object>)o));
			
		}else if(o instanceof String[]){
			xml.append(dealPrototypeArray((String[])o));
			
		}else if(o instanceof Integer[]){
			xml.append(dealPrototypeArray((Integer[])o));
			
		}else if(o instanceof Short[]){
			xml.append(dealPrototypeArray((Short[])o));
			
		}else if(o instanceof Long[]){
			xml.append(dealPrototypeArray((Long[])o));
			
		}else if(o instanceof Float[]){
			xml.append(dealPrototypeArray((Float[])o));
			
		}else if(o instanceof Double[]){
			xml.append(dealPrototypeArray((Double[])o));
			
		}else if(o instanceof Boolean[]){
			xml.append(dealPrototypeArray((Boolean[])o));
			
		}else if(o instanceof Object[]){
			xml.append(dealObjectArray((Object[])o));
		}else{
			throw new SystemError(new Object(),new Object[]{},"不支持使用自定义对象作为结果集！");
		}
		
		return xml.toString();
	}
	
	/**
	 * 转换Collection类型为xml字符串
	 * @param coll
	 * @return
	 */
	private static String dealCollection(Collection<Object> coll){
		StringBuilder xml = new StringBuilder();
		xml.append("<list>");
		Iterator<Object> iter = coll.iterator();
		Object o = null;
		while(iter.hasNext()){
			o = iter.next();
			xml.append("<value>")
			.append(dealObject(o))
			.append("</value>");
		}
		xml.append("</list>");
		return xml.toString();
	}
	
	/**
	 * 转换原型数组为xml字符串。
	 * 这里的Object[]只能是原型类型的数组，否则转换得到的内容是哈希字符串。
	 * @param array
	 */
	private static String dealPrototypeArray(Object[] array){
		StringBuilder xml = new StringBuilder();
		xml.append("<list>");
		for(Object s : array){
			xml.append("<value>")
			.append(s.toString())
			.append("</value>");
		}
		xml.append("</list>");
		return xml.toString();
	}
	
	/**
	 * 转换Object[]数据为xml字符串。
	 * @param array
	 * @return
	 */
	private static String dealObjectArray(Object[] array){
		StringBuilder xml = new StringBuilder();
		xml.append("<list>");
		for(Object s : array){
			xml.append("<value>")
			.append(dealObject(s))
			.append("</value>");
		}
		xml.append("</list>");
		return xml.toString();
	}
	
}
